
//
// Copyright (c) 2008, the /*jupiter jazz*/ group
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//     * Neither the name of the /*jupiter jazz*/ group nor the
//       names of its contributors may be used to endorse or promote products
//       derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY the /*jupiter jazz*/ group ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL the /*jupiter jazz*/ group BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//

#ifndef CLASSLIB_CONCEPTS_H
#define CLASSLIB_CONCEPTS_H

namespace foundation
{

//
// Private copy constructor and copy assignment ensure classes derived
// from class NonCopyable cannot be copied or constructed by copy.
// Taken from boost (http://www.boost.org/boost/noncopyable.hpp).
//

class NonCopyable
{
  protected:
    // Class NonCopyable has protected constructor and destructor members
    // to emphasize that it is to be used only as a base class.
    NonCopyable() {}
    ~NonCopyable() {}

  private:
    // Prevent NonCopyable class and any class inheriting it from being
    // copied or constructed by copy.
    NonCopyable(const NonCopyable&);
    const NonCopyable& operator=(const NonCopyable&);
};


//
// A classical singleton class, ensuring that a class has only one instance,
// and providing a global point of access to it. This implementation of the
// singleton idiom can be used safely in a multithreaded environment.
//
// The template parameter must be a default-constructible type.
//
// Example:
//
//   class Log
//     : public Singleton<Log>
//   {
//     public:
//       // Constructor.
//       Log();             // called before main() is entered
//
//       // Destructor.
//       ~Log();            // called after main() has returned
//
//       // Write a string to the log.
//       void write(const char* s);
//   };
//
//   Log::instance().write("Hello World");
//

template <typename T>
class Singleton
{
  public:
    typedef T ObjectType;

    // Return the unique instance of this class.
    static ObjectType& instance()
    {
        static ObjectType object;
        return object;
    }

  protected:
    // Allow derived class to have a constructor and a destructor.
    Singleton() {}
    virtual ~Singleton() {}

  private:
    // Also prevent it from being copied or constructed by copy.
    Singleton(const Singleton&);
    const Singleton& operator=(const Singleton&);

    // Static member ensuring that instance() is called a first time
    // before main() is called, to ensure proper multithreaded behavior.
    struct CreateIntance
    {
        CreateIntance()
        {
            Singleton<T>::instance();
        }
    };
    static CreateIntance dummy;
};


//
// ICloneable interface.
//

class ICloneable
  : public NonCopyable
{
  public:
    // Destructor.
    virtual ~ICloneable() {}

    // Return an exact copy of this object.
    virtual ICloneable* clone() const = 0;
};


//
// A COM-like IUnknown interface.
//
// At the moment, only the Release method is implemented, and it behaves
// differently than the COM IUnknown::Release in that it simply deletes
// the instance, whereas the COM one decrements the reference count by 1.
// The other two methods, IUnknown::AddRef and IUnknown::QueryInterface,
// are not yet supported.
//

class IUnknown
  : public NonCopyable
{
  public:
    // Delete this instance.
    // Use this method to delete an instance which was created by a
    // factory. This ensures that an instance is created and deleted
    // using the same memory subsystem, for example if the factory
    // resides inside a DLL. Do not use this method to delete an
    // instance which was created using the new operator. In this case,
    // simply use the delete operator.
    virtual void release() = 0;

  protected:
    ~IUnknown() {}
};

}       // namespace foundation

#endif  // !CLASSLIB_CONCEPTS_H
